import {Observable} from 'rxjs';
import {GnOAuthConfig} from './oauth-config';
import {GnLoginUser, GnMessageService, GnSiteInfo} from '../app';
import {HttpClient} from '@angular/common/http';
import {ActivatedRoute, Router} from '@angular/router';
import {GnOAuthSession} from './oauth-session';
import {Injectable} from '@angular/core';

@Injectable()
export class GnOAuth {

  constructor(private config: GnOAuthConfig,
              private session: GnOAuthSession,
              private loginUser: GnLoginUser,
              private siteInfo: GnSiteInfo,
              private messageService: GnMessageService,
              private http: HttpClient,
              private router: Router,
              private activateRoute: ActivatedRoute) {

    const json = sessionStorage.getItem('OAuthSession');
    if (json) {
      Object.assign(this, JSON.parse(json));
    }

  }

  login(): void {
    this.loginUser.load();
    if (this.loginUser.isLogin) {
      this.messageService.clean();
      const entryUrl = sessionStorage.getItem('blockUrl');
      this.router.navigateByUrl(entryUrl);
      return;
    }

    this.config.load()
      .subscribe(config => {
        this.session.refresh();
        const params = [
          'response_type=' + config.responseType,
          'state=' + this.session.state,
          'client_id=' + config.clientId,
          'scope=' + config.scope,
          'redirect_uri=' + encodeURIComponent(config.redirectUri),
          'code_challenge=' + this.session.codeChallenge,
          'code_challenge_method=S256'
        ];
        window.location.href = config.oidcConfig.authorization_endpoint + '?' + params.join('&');
      });
  }

  getToken(): Observable<any> {
    return new Observable<any>((observer) => {
      this.activateRoute.queryParams.subscribe(value => {
        if (value.state !== this.session.state) {
          observer.error(new Error('state不匹配'));
          return;
        }

        this.config.load()
          .subscribe(config => {
            const params = [
              'grant_type=authorization_code',
              'redirect_uri=' + encodeURIComponent(this.config.redirectUri),
              'client_id=' + this.config.clientId,
              'code=' + value.code,
              'code_verifier=' + this.session.codeVerifier
            ];

            this.http.post(config.oidcConfig.token_endpoint, params.join('&'), {
              headers: {
                'Content-type': 'application/x-www-form-urlencoded'
              }
            }).subscribe((resp: any) => {
              observer.next(resp);
            });
          });
      });
    });
  }
}
